#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;

//Semaphore semaphore;
Semaphore c1,c2,c3,c4,c5;	//每个信号量表示一个筷子
int q=2e8;

void Socrates(void *arg){
    int delay=q;
    while (1)	{
        printf("Socrates   : I am thinking. \n");
        //think
        while (delay) delay--;
        delay=q;
        printf("Socrates   : I am hungry, I want to eat.\n");
        c1.P();
        printf("Socrates   : I get 1 chopstick  : c1\n");
        while (delay) delay--;
        delay=q;
        c2.P();
        printf("Socrates   : I get 2 chopsticks : c1 , c2\n");
        printf("Socrates   : I am eating. It is delicious!!\n");
        //eat
        while (delay) delay--;
        delay=q;
        c2.V();
        c1.V();
    }
}
void Aristotle(void *arg){
    int delay=q;
    while (1)	{
        printf("Aristotle  : I am thinking. \n");
        //think
        while (delay) delay--;
        delay=q;
        printf("Aristotle  : I am hungry, I want to eat.\n");
        c3.P();
        printf("Aristotle  : I get 1 chopstick  : c3\n");
        while (delay) delay--;
        delay=q;
        c2.P();
        printf("Aristotle  : I get 2 chopsticks : c3 , c2\n");
        printf("Aristotle  : I am eating. It is delicious!!\n");
        //eat
        while (delay) delay--;
        delay=q;
        c2.V();
        c3.V();
    }
}
void Plato(void *arg){
    int delay=q;	
    while (1)	{
        printf("Plato      : I am thinking. \n");
        //think
        while (delay) delay--;
        delay=q;
        printf("Plato      : I am hungry, I want to eat.\n");
        c3.P();
        printf("Plato      : I get 1 chopstick  : c3\n");
        while (delay) delay--;
        delay=q;
        c4.P();
        printf("Plato      : I get 2 chopsticks : c3 , c4\n");
        printf("Plato      : I am eating. It is delicious!!\n");
        //eat
        while (delay) delay--;
        delay=q;
        c4.V();
        c3.V();
    }
}
void Democritus(void *arg){
    int delay=q;
    while (1)	{
        printf("Democritus : I am thinking. \n");
        //think
        while (delay) delay--;
        delay=q;
        printf("Democritus : I am hungry, I want to eat.\n");
        c5.P();
        printf("Democritus : I get 1 chopstick  : c5\n");
        while (delay) delay--;
        delay=q;
        c4.P();
        printf("Democritus : I get 2 chopsticks : c5 , c4\n");
        printf("Democritus : I am eating. It is delicious!!\n");
        //eat
        while (delay) delay--;
        delay=q;
        c4.V();
        c5.V();
    }
}
void Anaxagoras(void *arg){
    int delay=q;
    while (1)	{
        printf("Anaxagoras : I am thinking. \n");
        //think
        while (delay) delay--;
        delay=q;
        printf("Anaxagoras : I am hungry, I want to eat.\n");
        c5.P();
        printf("Anaxagoras : I get 1 chopstick  : c5\n");
        while (delay) delay--;
        delay=q;
        c1.P();
        printf("Anaxagoras : I get 2 chopsticks : c5 , c1\n");
        printf("Anaxagoras : I am eating. It is delicious!!\n");
        //eat
        while (delay) delay--;
        delay=q;
        c1.V();
        c5.V();
    }
}

void first_thread(void *arg)
{
    // 第1个线程不可以返回,下面循环是清屏操作
    stdio.moveCursor(0);
    for (int i = 0; i < 25 * 80; ++i)
    {
        stdio.print(' ');
    }
    stdio.moveCursor(0);

    printf("-----Long long ago,there are five philosophers having dinner together.\n");
    printf("-----They are Socrates,Aristotle,Plato,Democritus and Anaxagoras.\n");
    printf("-----Now they begin to eat and think: \n");
    c1.initialize(1);
    c2.initialize(1);
    c3.initialize(1);
    c4.initialize(1);
    c5.initialize(1);
	
    programManager.executeThread(Socrates, nullptr, "second thread", 1);
    programManager.executeThread(Aristotle, nullptr, "third thread", 1);
    programManager.executeThread(Plato, nullptr, "forth thread", 1);
    programManager.executeThread(Democritus, nullptr, "fifth thread", 1);
    programManager.executeThread(Anaxagoras, nullptr, "sixth thread", 1);

    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}
